/**
 * 
 */
package kiven.jee.model;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Transient;

import kiven.jee.model.support.TreeEntityUtil;

/**
 * 应用于自身关联的无限制级树形基类
 * 
 * @author kiven
 * @date 2013-02-28
 * 
 */
@SuppressWarnings({ "unchecked", "serial", "rawtypes" })
@MappedSuperclass
public abstract class TreeEntity<E extends TreeEntity> implements IBaseEntity {
	// 节点名称
	protected String name;
	// 节点位置
	protected Integer sortOrder;
	// 父节点
	protected E parent = null;
	// 孩子节点
	protected Set<E> children = new HashSet<E>();

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getSortOrder() {
		return sortOrder;
	}

	public void setSortOrder(Integer sortOrder) {
		this.sortOrder = sortOrder;
	}

	@ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE})
	public E getParent() {
		return parent;
	}

	public void setParent(E parent) {
		this.parent = parent;
	}

	@OneToMany(mappedBy = "parent",cascade = {CascadeType.ALL},fetch = FetchType.LAZY)
	@OrderBy("sortOrder asc")
	public Set<E> getChildren() {
		return children;
	}

	public void setChildren(Set<E> children) {
		this.children = children;
	}
	
	/**
	 * 增加孩子节点
	 * 
	 * @param entity 孩子节点
	 */
	@Transient
	public void addChild(E entity) {
		children.add(entity);
	}
	
	/**
	 * 获得节点名称
	 * 
	 * @return
	 */
	@Transient
	public String getText() {
		return getName();
	}
	
	/**
	 * 移除孩子节点
	 * 
	 * @param entity 孩子节点
	 */
	@Transient
	public void removeChild(E entity) {
		if (getChildren() != null && getChildren().size() > 0
				&& getChildren().contains(entity)) {
			children.remove(entity);
		}
		entity.setParent(null);
	}
	
	/**
	 * 是否为跟节点
	 * @return
	 */
	@Transient
	public boolean isRoot() {
		return (getParent() == null);
	}
	
	/**
	 * 是否为叶子节点
	 * @return
	 */
	@Transient
	public boolean isLeaf() {
		return (getChildren() == null || (getChildren() != null && getChildren()
				.size() == 0));
	}
	
	/**
	 * 判断自己是否为某节点的孩子
	 * @param entity
	 * @return
	 */
	@Transient
	public boolean isChildOf(E entity) {
		return TreeEntityUtil.isParentOf(entity, this);
	}
	
	/**
	 * 判断自己是否为某节点的父节点
	 * @param entity
	 * @return
	 */
	@Transient
	public boolean isParentOf(E entity) {
		return TreeEntityUtil.isParentOf(this, entity);
	}
	
	/**
	 * 不允许将外键关系设置成环状. 就是说，本节点的子节点中，如果包含parent，就不能把parent设置为本节点的上级节点
	 * 
	 * @param parentNode 父节点
	 * @return
	 */
	@Transient
	public boolean isDeadLock(E parentNode) {
		return false;
	}
}
